﻿using System;
using System.Reflection;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using SharePointOfView.SPReporting.Jobs;

namespace SharePointOfView.SPReporting.EventReceivers
{
    public class JobInstallFeatureReceiver : SPFeatureReceiver
    {
        /// <summary>
        /// On activation, add the job defined in Feature's properties
        /// </summary>
        /// <param name="properties">Context properties</param>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPFeatureProperty jobDisplayNameFeature = properties.Feature.Properties[Globals.JobDisplayNameFeaturePropertyName];
            SPFeatureProperty jobNameFeature = properties.Feature.Properties[Globals.JobNameFeaturePropertyName];
            SPFeatureProperty jobReportSourceFeature = properties.Feature.Properties[Globals.JobReportSourceFeaturePropertyName];
            SPFeatureProperty jobTypeNameFeature = properties.Feature.Properties[Globals.JobTypeNameFeaturePropertyName];
            SPFeatureProperty jobAssemblyNameFeature = properties.Feature.Properties[Globals.JobAssemblyNameFeaturePropertyName];
            SPFeatureProperty jobScheduleTypeFeature = properties.Feature.Properties[Globals.JobScheduleTypeFeaturePropertyName];
            SPFeatureProperty jobScheduleBeginFeature = properties.Feature.Properties[Globals.JobScheduleBeginFeaturePropertyName];
            SPFeatureProperty jobScheduleEndFeature = properties.Feature.Properties[Globals.JobScheduleEndFeaturePropertyName];
            SPFeatureProperty jobScheduleIntervalFeature = properties.Feature.Properties[Globals.JobScheduleIntervalFeaturePropertyName];
            SPFeatureProperty jobLockTypeFeature = properties.Feature.Properties[Globals.JobScopeFeaturePropertyName];

            // TODO : add log
            if (jobNameFeature == null || jobReportSourceFeature == null || jobTypeNameFeature == null || jobDisplayNameFeature == null) return;

            SPJobLockType jobLockType = SPJobLockType.Job;
            if (jobLockTypeFeature != null) jobLockType = (SPJobLockType)Enum.Parse(typeof(SPJobLockType), jobLockTypeFeature.Value);

            // Clean up job if already added
            JobUtilities.CleanUpJob(jobNameFeature.Value);

            // Install the job.
            Assembly assmblyFile = Assembly.Load(jobAssemblyNameFeature.Value); //recupération de l'assembly
            Module[] modFile = assmblyFile.GetModules(); //recup des modules
            Type[] typsFile = modFile[0].GetTypes(); //des types
            foreach (Type oType in typsFile)
            {
                if (oType.IsSubclassOf(typeof (GenericReportingJobDefinition)))
                {
                    var args = new Object[4];
                    args[0] = jobNameFeature.Value;
                    args[1] = string.IsNullOrEmpty(jobDisplayNameFeature.Value) ? jobNameFeature.Value : jobDisplayNameFeature.Value;
                    args[2] = jobReportSourceFeature.Value;
                    args[3] = jobLockType;

                    //Create Instance
                    var reportingJob = (GenericReportingJobDefinition) oType.InvokeMember(null,
                                                                                          BindingFlags.DeclaredOnly |
                                                                                          BindingFlags.Public |
                                                                                          BindingFlags.NonPublic |
                                                                                          BindingFlags.Instance |
                                                                                          BindingFlags.CreateInstance,
                                                                                          null, null, args);

                    SPSchedule schedule = null;
                    TimeSpan tsBegin = TimeSpan.Parse(jobScheduleBeginFeature.Value);
                    TimeSpan tsEnd = TimeSpan.Parse(jobScheduleEndFeature.Value);
                    switch (jobScheduleTypeFeature.Value)
                    {
                        case "Daily":
                            schedule = new SPDailySchedule();
                            ((SPDailySchedule) schedule).BeginHour = tsBegin.Hours;
                            ((SPDailySchedule) schedule).EndHour = tsEnd.Hours;
                            ((SPDailySchedule) schedule).BeginMinute = tsBegin.Minutes;
                            ((SPDailySchedule) schedule).EndMinute = tsEnd.Minutes;
                            ((SPDailySchedule) schedule).BeginSecond = tsBegin.Seconds;
                            ((SPDailySchedule) schedule).EndSecond = tsEnd.Seconds;
                            break;
                        case "Hourly":
                            schedule = new SPHourlySchedule();
                            ((SPHourlySchedule) schedule).BeginMinute = tsBegin.Minutes;
                            ((SPHourlySchedule) schedule).EndMinute = tsEnd.Minutes;
                            break;
                        case "Minute":
                            schedule = new SPMinuteSchedule();
                            ((SPMinuteSchedule) schedule).BeginSecond = tsBegin.Seconds;
                            ((SPMinuteSchedule) schedule).EndSecond = tsEnd.Seconds;
                            ((SPMinuteSchedule) schedule).Interval = Convert.ToInt32(jobScheduleIntervalFeature.Value);
                            break;
                    }

                    if (schedule == null)
                    {
                        // Do one time schedule
                        schedule = new SPOneTimeSchedule(DateTime.Now);
                    }

                    // Set scheduling
                    reportingJob.Schedule = schedule;
                    reportingJob.Update();
                }
            }
        }

        /// <summary>
        /// On deactivation, remove job
        /// </summary>
        /// <param name="properties">Context properties</param>
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            // Retrieve job's name
            SPFeatureProperty jobNameFeature = properties.Feature.Properties[Globals.JobNameFeaturePropertyName];
            // Make sure the job isn't already registered.
            JobUtilities.CleanUpJob(jobNameFeature.Value);
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
            // Not used
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
            // Not used
        }
    }
}